package top.suven.http.oauth.validator;

import org.apache.oltu.oauth2.as.request.OAuthRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;

/**
 * 2018-08-01
 * <p/>
 * 对各类 OAuthResponse的请求进行校验反回结果实现公共类
 * 将通用的行为(方法) 位于此
 *
 * @author suven.wang
 */
public abstract class OAuthResponseValidator {

    protected static final Logger logger = LoggerFactory.getLogger(OAuthResponseValidator.class);



    protected OAuthRequest oauthRequest;


    protected OAuthResponseValidator(OAuthRequest oauthRequest) {
        this.oauthRequest = oauthRequest;
    }


    /**
     * invalid_client	unknown client id	client_id”、“client_secret”参数无效。
     */
    public OAuthResponse invalidClientErrorResponse() throws OAuthSystemException {
        return   OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
                .setError(OAuthError.TokenResponse.INVALID_CLIENT)
//                .setErrorDescription("Invalid client_id '" + oauthRequest.getClientId() + "'")
                .setErrorDescription(OAuthErrorConstants.ERROR_CLIENT_MSG)
                .buildJSONMessage();
    }

    /**
     * “redirect_uri”所在的根域与开发者注册应用时所填写的根域名不匹配。
     */
    public OAuthResponse invalidRedirectUriResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.CodeResponse.INVALID_REQUEST)
//                .setErrorDescription("Invalid redirect_uri '" + oauthRequest.getRedirectURI() + "'")
                .setErrorDescription(OAuthErrorConstants.INVALID_REDIRECT_URI)
                .buildJSONMessage();
    }

    /**
     * The requested scope is exceeds the scope granted by the resource owner
     * 请求的“scope”参数是无效的、未知的、格式不正确的、或所请求的权限范围超过了数据拥有者所授予的权限范围。
     */
    public OAuthResponse invalidScopeResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.CodeResponse.INVALID_SCOPE)
//                .setErrorDescription("Invalid scope '" + oauthRequest.getScopes() + "'")
                .setErrorDescription(OAuthErrorConstants.ERROR_UNKNOW)
                .buildJSONMessage();
    }

    /**
     * invalid_client	unknown client id	client_id”、“client_secret”参数无效。
     */
    public OAuthResponse invalidClientSecretResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
                .setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)
//                .setErrorDescription("Invalid client_secret by client_id '" + oauthRequest.getClientId() + "'")
                .setErrorDescription(OAuthErrorConstants.ERROR_CLIENT_MSG)
                .buildJSONMessage();
    }

    /**
     * invalid_grant	The provided authorization grant is revoked	提供的Access Grant是无效的、过期的或已撤销的，
     * 例如，Authorization Code无效(一个授权码只能使用一次)、Refresh Token无效、
     * redirect_uri与获取Authorization Code时提供的不一致、Devie Code无效(一个设备授权码只能使用一次)等。
     */
    public OAuthResponse invalidUsernamePasswordResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.TokenResponse.INVALID_GRANT)
                .setErrorDescription(OAuthErrorConstants.ERROR_PASSWORD)
                .buildJSONMessage();
    }

    /**
     * iinvalid_request	invalid refresh token	请求缺少某个必需参数，包含一个不支持的参数或参数值，或者格式不正确。
     */
    public OAuthResponse invalidStateResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.CodeResponse.INVALID_REQUEST)
//                .setErrorDescription("Parameter 'state'  is required")
                .setErrorDescription(OAuthErrorConstants.ERROR_PARAMETER_STATE)
                .buildJSONMessage();
    }

    /**
     * invalid_grant	The provided authorization grant is revoked	提供的Access Grant是无效的、过期的或已撤销的
     * ，例如，Authorization Code无效(一个授权码只能使用一次)、Refresh Token无效、
     * redirect_uri与获取Authorization Code时提供的不一致、
     * Devie Code无效(一个设备授权码只能使用一次)等。
     */
    public OAuthResponse invalidGrantTypeResponse(String grantType) throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
                .setError(OAuthError.TokenResponse.INVALID_GRANT)
                .setErrorDescription("Invalid grant_type '" + grantType + "'")
                .buildJSONMessage();
    }
    /**
     * invalid_grant	The provided authorization grant is revoked	提供的Access Grant是无效的、过期的或已撤销的
     * ，例如，Authorization Code无效(一个授权码只能使用一次)、Refresh Token无效、
     * redirect_uri与获取Authorization Code时提供的不一致、
     * Devie Code无效(一个设备授权码只能使用一次)等。
     */
    public OAuthResponse invalidResponseTypeResponse(String responseType) throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
                .setError(OAuthError.CodeResponse.UNSUPPORTED_RESPONSE_TYPE)
                .setErrorDescription("Invalid response_ype '" + responseType + "'")
                .buildJSONMessage();
    }


    /**
     * authorization_declined	User has declined the authorization	Device Flow中，
     * 用户拒绝了对Device Code的授权操作。
     */
    public OAuthResponse invalidCodeResponse(String code) throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.TokenResponse.INVALID_GRANT)
                .setErrorDescription("Invalid code '" + code + "'")
                .buildJSONMessage();
    }




    /**
     * invalid_request	invalid refresh token
     * 请求缺少某个必需参数，包含一个不支持的参数或参数值，或者格式不正确。
     * expired_token	refresh token has been used	提供的Refresh Token已过期
     */
    public OAuthResponse invalidRefreshTokenResponse(String refreshToken) throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.TokenResponse.INVALID_GRANT)
                .setErrorDescription("Invalid refresh_token: " + refreshToken)
                .setErrorDescription(OAuthErrorConstants.INVALID_ACCESS_TOKEN)
                .buildJSONMessage();
    }

    /**
     * invalid_request	invalid refresh token
     * 请求缺少某个必需参数，包含一个不支持的参数或参数值，或者格式不正确。
     * expired_token	refresh token has been used	提供的Refresh Token已过期
     */
    public OAuthResponse invalidTokenResponse(long userId) throws OAuthSystemException {
        return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.TokenResponse.INVALID_GRANT)
                .setErrorDescription("Invalid create_token false to userId: " + userId)
                .setErrorDescription(OAuthErrorConstants.ERROR_ACCESS_TOKEN)
                .buildJSONMessage();
    }


    public OAuthResponse invalidExceptionResponse(OAuthProblemException e) throws OAuthSystemException{
        OAuthResponse oAuthResponse = OAuthASResponse
                .errorResponse(HttpServletResponse.SC_FOUND)
                .location(e.getRedirectUri())
                .error(e)
                .buildJSONMessage();

        return oAuthResponse;

    }

    /**
     * token 过期错误提醒;
     * @param accessToken
     * @return
     * @throws OAuthSystemException
     */
    public OAuthResponse expiredTokenResponse(String accessToken,String redirectUri) throws OAuthSystemException {
        logger.debug("AccessToken [{}] is expired,redirectUri[{}] ", accessToken,redirectUri);
        final OAuthResponse oAuthResponse = OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND)
                .setError(OAuthError.ResourceResponse.EXPIRED_TOKEN)
                .setErrorDescription("access_token '" + accessToken + "' expired")
                .setErrorUri(redirectUri)
                .buildJSONMessage();
        return oAuthResponse;
    }




    /** Authorization接口返回对象 **/
    public OAuthResponse successDefault() throws OAuthSystemException {
        OAuthResponse.OAuthResponseBuilder builder = new OAuthResponse
                .OAuthResponseBuilder(HttpServletResponse.SC_OK);
        return builder.buildJSONMessage();

    }







}
